#include "coordRef.h"
#include "stdio.h"
#include "geometry.h"
#include <cstddef>

#define ACCEPT_USE_OF_DEPRECATED_PROJ_API_H
#include "proj_api.h"

CoordRef::CoordRef()
{
    wgs84_ = pj_init_plus("+proj=latlong +ellps=WGS84 +datum=WGS84");
}

CoordRef::~CoordRef()
{
    if(wgs84_)
    {
        pj_free(wgs84_);
        wgs84_ = nullptr;
    }
    if(gkp_)
    {
        pj_free(gkp_);
        gkp_ = nullptr;
    }
}

double CoordRef::GetZoneMeridian(int nZoneID)
{
    double dMinLon = 1.5 + 3.0 * (nZoneID-1);
	double dMaxLon = dMinLon + 3.0;

	if (dMinLon > 180.0)
	{
		dMinLon -= 180.0;
	}

	if (dMaxLon > 180.0)
	{
		dMaxLon -= 180.0;
	}

    return dMinLon + 0.5*(dMaxLon - dMinLon);
}

int CoordRef::GetZoneID(double longitude)
{
    if (longitude > 180.0 || longitude < -180.0)
    {
        return -1;
    }

    if (longitude < 1.5)
    {
        longitude += 360.0;
    }
    return std::floor((longitude - 1.5) / 3.0) + 1;
}

bool CoordRef::WGS2GKP(double longitude, double latitude, double altitude,  double& x, double& y, double& z)
{
    int nZoneID = GetZoneID(longitude);
    if(nZoneID != cur_zoneID_)
    {
        if(gkp_ != nullptr)
        {
            pj_free(gkp_);
            gkp_ = NULL;
        }

        cur_zoneID_ = nZoneID;
        char szText[256];
	    sprintf(szText, "+proj=tmerc +ellps=WGS84 +datum=WGS84 +x_0=500000 +lon_0=%.2lf +units=m", GetZoneMeridian(nZoneID));
        gkp_ = pj_init_plus(szText);
    }

    x = geometry::D2R(longitude);
    y = geometry::D2R(latitude);
    z = altitude / 100.0;
    pj_transform(wgs84_, gkp_, 1, 1, &x, &y, &z);
    return true;
}